package org.example.rmsmsapi.Utils;


import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SM4Utils {
    private String secretKey = "";
    private String iv = "";
    private boolean hexString = false;
    private static String hexStrings = "0123456789ABCDEF";

    public String getSecretKey() {
        return this.secretKey;
    }

    public void setSecretKey(String secretKey) {
        this.secretKey = secretKey;
    }

    public boolean isHexString() {
        return this.hexString;
    }

    public void setHexString(boolean hexString) {
        this.hexString = hexString;
    }

    public SM4Utils() {
    }

    public String encryptData_ECB(String plainText) throws Exception {
        SM4_Context ctx = new SM4_Context();
        ctx.isPadding = true;
        ctx.mode = 1;
        byte[] keyBytes = this.secretKey.getBytes();
        SM4 sm4 = new SM4();
        sm4.sm4_setkey_enc(ctx, keyBytes);
        byte[] encrypted = sm4.sm4_crypt_ecb(ctx, plainText.getBytes("utf-8"));
        String cipherText = this.byteToHex(encrypted);
        if (cipherText != null && cipherText.trim().length() > 0) {
            Pattern p = Pattern.compile("\\s*|\t|\r|\n");
            Matcher m = p.matcher(cipherText);
            cipherText = m.replaceAll("");
        }

        return cipherText;
    }

    public String byteToHex(byte[] data) {
        String hexString = "";

        for(int i = 0; i < data.length; ++i) {
            String hex = Integer.toHexString(data[i] & 255);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }

            hexString = hexString + hex;
        }

        return hexString.toUpperCase();
    }

    public String decryptData_ECB(String cipherText) throws IOException, Exception {
        SM4_Context ctx = new SM4_Context();
        ctx.isPadding = true;
        ctx.mode = 0;
        byte[] keyBytes = this.secretKey.getBytes();
        SM4 sm4 = new SM4();
        sm4.sm4_setkey_dec(ctx, keyBytes);
        ByteArrayOutputStream baos = new ByteArrayOutputStream(cipherText.length() / 2);

        for(int i = 0; i < cipherText.length(); i += 2) {
            baos.write(hexStrings.indexOf(cipherText.charAt(i)) << 4 | hexStrings.indexOf(cipherText.charAt(i + 1)));
        }

        byte[] bytes = baos.toByteArray();
        String str = (new BASE64Encoder()).encode(bytes);
        byte[] decrypted = sm4.sm4_crypt_ecb(ctx, (new BASE64Decoder()).decodeBuffer(str));
        return new String(decrypted, "utf-8");
    }

    public byte[] hexStringtobyt(String hexString) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream(hexString.length() / 2);

        for(int i = 0; i < hexString.length(); i += 2) {
            baos.write(hexString.indexOf(hexString.charAt(i)) << 4 | hexString.indexOf(hexString.charAt(i + 1)));
        }

        byte[] data = baos.toByteArray();
        baos.close();
        return data;
    }

    public String encryptData_CBC(String plainText) throws Exception {
        SM4_Context ctx = new SM4_Context();
        ctx.isPadding = true;
        ctx.mode = 1;
        byte[] keyBytes = this.secretKey.getBytes();
        byte[] ivBytes = this.iv.getBytes();
        SM4 sm4 = new SM4();
        sm4.sm4_setkey_enc(ctx, keyBytes);
        byte[] encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, plainText.getBytes("utf-8"));
        String cipherText = (new BASE64Encoder()).encode(encrypted);
        if (cipherText != null && cipherText.trim().length() > 0) {
            Pattern p = Pattern.compile("\\s*|\t|\r|\n");
            Matcher m = p.matcher(cipherText);
            cipherText = m.replaceAll("");
        }

        return cipherText;
    }

    public String decryptData_CBC(String cipherText) throws Exception {
        SM4_Context ctx = new SM4_Context();
        ctx.isPadding = true;
        ctx.mode = 0;
        byte[] keyBytes = this.secretKey.getBytes();
        byte[] ivBytes = this.iv.getBytes();
        SM4 sm4 = new SM4();
        sm4.sm4_setkey_dec(ctx, keyBytes);
        byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, (new BASE64Decoder()).decodeBuffer(cipherText));
        return new String(decrypted, "GBK");
    }

}
